/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package br.com.aggjpsv.libraryserver;

import br.com.aggjpsv.libraryserver.entities.Parametros;
import br.com.aggjpsv.libraryserver.entities.Request;
import br.com.aggjpsv.libraryserver.thread.HTTPResponseBasic;
import br.com.aggjpsv.libraryserver.thread.ThreadFactory;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level;

/**
 *
 * @author SergioPeres
 */
public abstract class FactoryAbstract {
    
    protected Parametros parametro;
    
    /**
     * Inicia os parametros (port e pathDir).
     * 
     * @param parametros passar para esta o args da main.
     */
    public FactoryAbstract(String[] parametros) {
        this.parametro = new Parametros();
        this.parametro.setParametros(parametros);
    }
    
    /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
    /* %%%%%%%% Metodos Abstratos %%%%%%%% */
    /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
    /**
     * Verifica qual é o tipo da requisição e retorna um Runnable para atende-la.
     * 
     * @param socket socket de conexão.
     * @return Runnable adequando para a requisição.
     */
    public abstract Runnable getService(Socket socket);
    
    public abstract HTTPResponseBasic getRespose(OutputStream output);
    
    /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
    /* %%%%%% Metodos Implementados %%%%%% */
    /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
    
    public Parametros getParametros() {
        return parametro;
    }
    
    /**
     * Crima uma fabrica de thread.
     * 
     * @return frabrica de thread.
     */
    protected ThreadFactory getThreadFactory() {
        return new ThreadFactory();
    }
    
    /**
     * Implementa o ExecutorService sem controle de concorrencias entre threads.
     * Utiliza ThreadFractory local.
     * 
     * @return pool de threads.
     */
    protected ExecutorService getExecutorsCached() {
        return Executors.newCachedThreadPool(getThreadFactory());
    }
    
    
    public ExecutorService getPoolThread() {
        return getExecutorsCached();
    }
    
    public String convertStreamToString(InputStream is) {
        if (is != null) {
            Writer writer = new StringWriter();

            char[] buffer = new char[2048];
            try {
                Reader reader = new BufferedReader(new InputStreamReader(is));
                int i = reader.read(buffer);
                writer.write(buffer, 0, i);
            } catch (IOException e) {
                System.out.println(Level.SEVERE + "\n\tErro ao converter stream para string \n" + e);
                return "";
            }
            return writer.toString();
        } else {
            return "";
        }
    }
    
    public Request getRequest(String requestString) {
        Request request = new Request();
        try {
            request.parse(requestString);
        } catch (IOException ex) {
            System.out.println("Erro. FactoryAbstract.getRequest\n" + ex.getMessage());
        }
        return request;
    }
}
